package demo.security.config;

import demo.security.realm.SpringDemoRealm;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

  /**
   * 配置自定义的Realm
   */
  @Bean
  public SpringDemoRealm getRealm() {
    return new SpringDemoRealm();
  }

  /**
   * 配置安全管理器
   */
  @Bean
  public SecurityManager securityManager(SpringDemoRealm realm) {
    //使用默认的安全管理器
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(realm);
    //将自定义的realm交给安全管理器统一调度管理
    securityManager.setRealm(realm);

    return securityManager;
  }

  /**
   * Filter工厂，设置对应的过滤条件和跳转条件
   */
  @Bean
  public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
    //1.创建shiro过滤器工厂
    ShiroFilterFactoryBean filterFactory = new ShiroFilterFactoryBean();

    //2.设置安全管理器
    filterFactory.setSecurityManager(securityManager);

    //3.通用配置（配置登录页面，登录成功页面，验证未成功页面）
    filterFactory.setLoginUrl("/autherror?code=1"); //设置登录页面
    filterFactory.setUnauthorizedUrl("/autherror?code=2"); //授权失败跳转页面

    //4.配置过滤器集合
      /*
       * key ：访问连接，支持通配符的形式
       * value：过滤器类型
       *
       * shiro常用过滤器
       * anno ：匿名访问（表明此链接所有人可以访问）
       * authc ：认证后访问（表明此链接需登录认证成功之后可以访问）
       */
    Map<String,String> filterMap = new LinkedHashMap<String,String>();
    // 配置不会被拦截的链接 顺序判断
    filterMap.put("/login", "anon");
    filterMap.put("/user/home", "anon");
    // 登录后才能访问的链接
    filterMap.put("/**", "authc");

    //5.设置过滤器
    filterFactory.setFilterChainDefinitionMap(filterMap);
    return filterFactory;
  }

  @Bean("lifecycleBeanPostProcessor")
  public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
    return new LifecycleBeanPostProcessor();
  }

  /**
   * 使@RequiresPermissions等注解生效
   * 如果项目依赖了spring-boot-starter-aop，则不需要像下面这样手动创建DefaultAdvisorAutoProxyCreator
   * @return
   */
  @Bean
  @DependsOn({"lifecycleBeanPostProcessor"})
  public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
    DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
    advisorAutoProxyCreator.setProxyTargetClass(true);
    return advisorAutoProxyCreator;
  }

  /**
   * 配置shiro注解支持
   */
  @Bean
  public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
    AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
    advisor.setSecurityManager(securityManager);
    return advisor;
  }

}
